package com.ronx.scs.aspects;

import com.ronx.scs.servlet.FreeMarkerDispatcherServlet;
import net.sf.ehcache.Cache;
import net.sf.ehcache.Element;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.nio.CharBuffer;

@Aspect
@Component
public class CachingAspect {
    private final static int DEFAULT_BUFFER_SIZE = 1024 * 8;

//    @Autowired
    public Cache ehCacheFactoryBean;

    @Pointcut("execution(* com.ronx.scs.servlet.FreeMarkerDispatcherServlet.aopCacheJoinPoint(..))")
    public void aopCacheJoinPoint() {
    }

    @Around("aopCacheJoinPoint()" + "&&" + "this(fmDispatcherServlet)")
    public Object cacheMVC(ProceedingJoinPoint proceedingJoinPoint, FreeMarkerDispatcherServlet fmDispatcherServlet) throws Throwable {
        Object[] arguments = proceedingJoinPoint.getArgs();
        fmDispatcherServlet.setStartFlag(false);
        String cacheKey = getCacheKey(proceedingJoinPoint);
        Element element = ehCacheFactoryBean.get(cacheKey);
        if (element == null) {
            ServletRequest servletRequest = (ServletRequest) arguments[0];
            HttpServletRequest httpRequest = (HttpServletRequest) servletRequest;
            StringBuffer requestURL = httpRequest.getRequestURL();
            URL url = new URL(requestURL.toString());
            URLConnection urlConnection = url.openConnection();
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
            StringBuilder stringBuilder = new StringBuilder();
            CharBuffer charBuffer = CharBuffer.allocate(DEFAULT_BUFFER_SIZE);
            while (bufferedReader.read(charBuffer) >= 0) {
                stringBuilder.append(charBuffer.flip());
                charBuffer.clear();
            }
            byte[] bytes = stringBuilder.toString().getBytes();
            bufferedReader.close();
            element = new Element(cacheKey, bytes);
            ehCacheFactoryBean.put(element);
//            System.out.println("PUT into cache " + new Date());
        } else {
//            System.out.println("GET from cache " + new Date());
        }
        ((ServletResponse) arguments[1]).setContentType("text/html");
        ((ServletResponse) arguments[1]).getOutputStream().write((byte[]) element.getObjectValue());

        fmDispatcherServlet.setStartFlag(true);
//        proceedingJoinPoint.proceed();

        return null;
    }

    private String getCacheKey(ProceedingJoinPoint proceedingJoinPoint) {
        Object[] arguments = proceedingJoinPoint.getArgs();
        StringBuilder stringBuilder =
            new StringBuilder(proceedingJoinPoint.getTarget().getClass().getSimpleName() + "." + proceedingJoinPoint.getSignature().getName());
        if ((arguments != null) && (arguments.length != 0)) {
            for (Object argument : arguments) {
                stringBuilder.append(".").append(argument);
            }
        }
        return stringBuilder.toString();
    }

//    public void setEhCacheFactoryBean(Cache ehCacheFactoryBean) {
//        this.ehCacheFactoryBean = ehCacheFactoryBean;
//    }
}
